<template>
  <!--中间面板-->
  <div class="center-board">
    <div class="action-bar">
<!-- 暂时隐藏，似乎还有点问题 -->
<!--       <el-button
        icon="el-icon-arrow-left"
        size="mini"
        :disabled="undoState"
        class="undo"
        @click="undo"
      >
      </el-button>
      <el-button
        icon="el-icon-arrow-right"
        size="mini"
        :disabled="redoState"
        class="redo"
        @click="redo"
      > -->
      </el-button>
      <el-button icon="el-icon-data-board" type="primary" size="mini" @click="preview">
        预览
      </el-button>
      <el-button
        icon="el-icon-tickets"
        type="primary"
        size="mini"
        @click="viewJSON"
        class="json"
      >
        JSON
      </el-button>
      <el-button icon="el-icon-video-play" type="primary" size="mini" @click="view">
        运行
      </el-button>
      <el-button icon="el-icon-delete-solid" type="danger" size="mini" @click="clear">
        清空
      </el-button>
      <el-button
        icon="el-icon-question"
        type="warning"
        size="mini"
        @click="help"
        style="background-color: #ff6600"
      >
        帮助
      </el-button>
    </div>
    <el-scrollbar class="center-scrollbar">
      <el-row class="center-board-row" :gutter="formConf.gutter">
        <el-form
          class="design-form"
          :size="formConf.size"
          :disabled="formConf.disabled"
          :label-position="formConf.labelPosition"
          :label-width="formConf.labelWidth + 'px'"
        >
          <draggable
            class="drawing-board"
            :list="list"
            :animation="100"
            group="componentsGroup"
          >
            <template v-for="element in list">
              <el-row :gutter="element.gutter" class="drawing-item">
                <design-item
                  :model="element"
                  :activeItem="activeItem"
                  @rowItemRollBack="handlerRollBack"
                  @onActiveItemChange="handlerActiveItemChange"
                  @copyItem="handlerItemCopy"
                  @deleteItem="handlerItemDelete"
                />
              </el-row>
            </template>
          </draggable>
          <div v-show="infoShow" class="empty-info">
            <el-empty description="从左侧拖拽添加控件"></el-empty>
          </div>
        </el-form>
      </el-row>
    </el-scrollbar>
    <config-panel
      ref="configPanel"
      @record="record"
      :activeItem="activeItem"
      :itemList="list"
      :formConf="formConf"
    />
    <!--
    <el-dialog :visible.sync="previewVisible" width="70%" title="预览"></el-dialog>
    -->
    <preview
      :visible.sync="previewVisible"
      :itemList="itemList"
      :formConf="formConf"
      v-if="previewVisible"
    />
    <json-code :visible.sync="JSONVisible" ref="jsonDrawer" :code="viewCode" />
    <!--
    <el-dialog :visible.sync="JSONVisible" width="70%" title="JSON" center :close-on-click-modal="false">
      <codemirror v-model="viewCode" :options="options" />
      <span slot="footer" class="dialog-footer">
        <el-button type="primary" @click="handlerSetJson()">确 定</el-button>
      </span>
    </el-dialog>
    -->
  </div>
</template>
<script>
// 核心样式
import "codemirror/lib/codemirror.css";
// 引入主题后还需要在 options 中指定主题才会生效
import "codemirror/theme/dracula.css";
import "codemirror/theme/blackboard.css";
import "codemirror/mode/javascript/javascript";

import { codemirror } from "vue-codemirror";
import draggable from "vuedraggable";
import configPanel from "./config-panel";
import designItem from "./design-item";
import { getSimpleId } from "./utils/IdGenerate";

import formConf from "./custom/formConf";
import preview from "./preview";
import jsonCode from "./json-code.vue";

import { isLayout, isTable, inTable, jsonClone } from "./utils/index";

export default {
  name: "designer",
  components: {
    draggable,
    configPanel,
    designItem,
    preview,
    jsonCode,
    codemirror,
  },
  props: {
    undoState: {
      type: Boolean,
      default: false,
    },
    redoState: {
      type: Boolean,
      default: false,
    },
    list: {
      type: Array,
      default: [],
    },
    formConfig: {
      type: Object,
      default: {},
    },
  },
  provide() {
    return {
      getContext: this,
    };
  },
  data() {
    return {
      formConf: formConf,
      activeItem: {},
      lastActiveItem: {},
      formConfVisible: false,
      previewVisible: false,
      JSONVisible: false,
      itemList: [],
      activeName: "formConf",
      editorCode: "",
      viewCode: "",
      // 默认配置
      options: {
        theme: "dracula", // 主题，对应主题库 JS 需要提前引入
        tabSize: 4, // 缩进格式
        lineNumbers: true, // 显示行号
        line: true,
        styleActiveLine: true, // 高亮选中行
        hintOptions: {
          completeSingle: true, // 当匹配只有一项的时候是否自动补全
        },
      },
    };
  },
  mounted() {},
  methods: {
    changeFormConfig(formConfig) {
      this.formConf = formConfig;
    },
    preview() {
      const clone = JSON.parse(JSON.stringify(this.list));
      this.itemList = clone;
      this.previewVisible = true;
    },
    viewJSON() {
      this.viewCode = this.code;
      if (this.$refs.jsonDrawer.editor) {
        this.$refs.jsonDrawer.editor.getDoc().setValue(this.code);
        this.$nextTick(() => {
          this.$refs.jsonDrawer.editor.refresh();
        });
      }
      this.JSONVisible = true;
    },
    view() {
      localStorage.setItem("formValue", this.code);
      window.open("#/view");
    },
    clear() {
      this.$confirm("此操作将清空整个表单,是否继续?").then(() => {
        this.$emit("clear");
      });
    },
    help() {
      window.open("https://my.oschina.net/wison?tab=newest&catalogId=12281843");
    },
    handlerActiveItemChange(obj) {
      this.lastActiveItem = this.activeItem;
      this.activeItem = obj;
    },
    handlerItemCopy(origin, parent) {
      if (isLayout(origin)) {
        //row
        const clone = jsonClone(origin);
        const uId = "row_" + getSimpleId();
        clone.id = uId;
        clone._id = uId;
        clone.columns.map((column) => {
          let itemList = [];
          column.list.map((item) => {
            const cloneItem = jsonClone(item);
            const uId = "fd_" + getSimpleId();
            cloneItem.id = uId;
            cloneItem._id = uId;
            itemList.push(cloneItem);
          });
          column.list = [];
          column.list = itemList;
        });
        this.list.push(clone);
        this.handlerActiveItemChange(clone);
      } else if (isTable(origin)) {
        //表格布局
        const clone = jsonClone(origin);
        const uId = "table_" + getSimpleId();
        clone.id = uId;
        clone._id = uId;
        clone.layoutArray.map((tr) => {
          tr.map((td) => {
            let itemList = [];
            td.id = getSimpleId();
            td.columns.map((item, i) => {
              const cloneItem = jsonClone(item);
              const uId = "fd_" + getSimpleId();
              cloneItem.id = uId;
              cloneItem._id = uId;
              itemList.push(cloneItem);
            });
            td.columns = [];
            td.columns = itemList;
          });
        });
        this.list.push(clone);
        this.handlerActiveItemChange(clone);
      } else {
        //如果是普通组件，需要判断他是否在布局组件下。
        if (parent) {
          if (inTable(parent)) {
            //增加表格组件的支持
            if (parent.columns.some((item) => item.id === origin.id)) {
              const clone = jsonClone(origin);
              const uId = "fd_" + getSimpleId();
              clone.id = uId;
              clone._id = uId;
              parent.columns.push(clone);
              this.handlerActiveItemChange(clone);
            }
          } else {
            parent.columns.map((column) => {
              if (column.list.some((item) => item.id === origin.id)) {
                const clone = jsonClone(origin);
                const uId = "fd_" + getSimpleId();
                clone.id = uId;
                clone._id = uId;
                column.list.push(clone);
                this.handlerActiveItemChange(clone);
              }
            });
          }
        } else {
          const clone = jsonClone(origin);
          const uId = "fd_" + getSimpleId();
          clone.id = uId;
          clone._id = uId;
          this.list.push(clone);
          this.handlerActiveItemChange(clone);
        }
      }
      this.$refs.configPanel.currentTab = "field";
    },
    handlerItemDelete(origin, parent) {
      if (isLayout(origin) || isTable(origin)) {
        //如果是布局组件,则直接删除
        const index = this.list.findIndex((item) => item.id === origin.id);
        this.list.splice(index, 1);
      } else {
        //如果不是布局组件，则先判断是不是在布局内部，如果不是，则直接删除就可以，如果是，则要在布局内部删除
        if (parent) {
          if (inTable(parent)) {
            //增加表格组件的支持
            const colIndex = parent.columns.findIndex((item) => item.id === origin.id);
            if (colIndex > -1) {
              parent.columns.splice(colIndex, 1);
            }
          } else {
            parent.columns.map((column) => {
              const colIndex = column.list.findIndex((item) => item.id === origin.id);
              if (colIndex > -1) {
                column.list.splice(colIndex, 1);
              }
            });
          }
        } else {
          const index = this.list.findIndex((item) => item.id === origin.id);
          this.list.splice(index, 1);
        }
      }
    },
    handlerSaveFormConf() {
      this.formConfVisible = false;
    },
    handlerRollBack(rowItem, oldIndex) {
      //还原
      this.list.splice(oldIndex, 0, rowItem);
    },
    handlerSetJson() {
      this.$emit("updateJSON", this.viewCode);
      this.JSONVisible = false;
    },
    undo() {
      this.$emit("undo");
    },
    redo() {
      this.$emit("redo");
    },
    record() {
      this.$emit("record");
    },
  },
  computed: {
    infoShow() {
      return this.list.length < 1;
    },
    code() {
      let json = {};
      json.config = this.formConf;
      json.list = this.list;
      return JSON.stringify(json, null, 4);
    },
  },
  watch: {
    activeItem(newValue, oldValue) {
      this.lastActiveItem = oldValue;
    },
  },
};
</script>
<style scoped>
.el-rate {
  display: inline-block;
}

.center-scrollbar >>> .el-scrollbar__bar.is-horizontal {
  display: none;
}

.center-scrollbar >>> .el-scrollbar__wrap {
  overflow-x: hidden;
}

.empty-info >>> .el-empty__description p {
  color: #ccb1ea;
  font-size: 16px;
}

.drawing-board >>> .el-radio.is-bordered + .el-radio.is-bordered {
  margin-left: 0px;
}

.drawing-board >>> .el-checkbox.is-bordered + .el-checkbox.is-bordered {
  margin-left: 0px;
}
</style>
<style lang="scss">
@import "./style/designer.scss";
</style>
<style>
@import "./style/designer.css";
</style>
